//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<IVar.h>
///	@path	~/src/object/
///	@date	2007/06/25
///	@desc	Generic variable interface.

#pragma once

#include "xeres.h"

// STL
#include <vector>

// math
#include "lib/math/pair.h"
#include "lib/math/vector.h"
#include "lib/math/quat.h"
#include "lib/math/matrix.h"
#include "lib/math/color.h"

#include "object/IObject.h"

namespace xeres {

	/*!
		\ingroup	iobject_module

		\class	IVar
		\brief	Interface of a public accessed variable.
		\details
			IVar provides a generic variable interface for value & object accessing.
			Basic type value & IObject instance can be stored in IVar instance for manipulating.<BR>
			At the same time, IVar provides a value passing interface, user can pass different value
			by/through IVar interface. Class derived from IVar can handles different value inputs.<BR>
			There're some basic types of value:<BR>
			<BR>
			\table
				\beginrow{ 30 }
					\entry{ \b Type	, center , 190 }	\entry{ \ref IOBJECTBASICTYPEGROUP \b ID , center , 190 }
					\entry{	\b Description , center , 230 }
				\row{ 30 }
					\entry{ Boolean	, center , 190 }	\entry{ \ref BOOL_TYPE_CLASS_ID , center , 190 }
					\entry{	True or false value. , center , 230 }
				\row{ 30 }
					\entry{ Integer	, center , 190 }	\entry{ \ref INT_TYPE_CLASS_ID , center , 190 }
					\entry{	Generic 32bit integer. , center , 230 }
				\row{ 30 }
					\entry{	Float	, center , 190 }	\entry{ \ref FLOAT_TYPE_CLASS_ID , center , 190 }
					\entry{	Generic 32bit single precision float. , left , 230 }
				\row{ 30 }
					\entry{	Pair	, center , 190 }	\entry{ \ref PAIR_TYPE_CLASS_ID , center , 190 }
					\entry{	2 floats grouped pair. , center , 230 }
				\row{ 30 }
					\entry{	Vector	, center , 190 }	\entry{ \ref VECTOR_TYPE_CLASS_ID , center , 190 }
					\entry{	3 floats grouped vector. , center , 230 }
				\row{ 30 }
					\entry{	Quat	, center , 190 }	\entry{ \ref QUAT_TYPE_CLASS_ID , center , 190 }
					\entry{	4 floats grouped quaternion. , center , 230 }
				\row{ 30 }
					\entry{	Color	, center , 190 }	\entry{ \ref COLOR_TYPE_CLASS_ID , center , 190 }
					\entry{	4 floats presents RGBA color. , center , 230 }
				\row{ 30 }
					\entry{	Matrix	, center , 190 }	\entry{ \ref MATRIX_TYPE_CLASS_ID , center , 190 }
					\entry{	4x4 floats matrix. , center , 230 }
				\row{ 30 }
					\entry{	String	, center , 190 }	\entry{ \ref STRING_TYPE_CLASS_ID , center , 190 }
					\entry{	UNICODE string. , center , 230 }
				\endrow
			\endtable
			<BR>
			These types of value can be accessed directly.<BR>
			<BR>
			If there's nothing or IVar is not defined, void type should be returned.<BR>
			<BR>
			\table
				\beginrow{ 30 }
					\entry{ Void	, center , 190 }	\entry{ \ref VOID_TYPE_CLASS_ID , center , 190 }
					\entry{	Nothing or variable not defined. , center , 230 }
				\endrow
			\endtable

			\eg	Demonstrates how to access value in IVar instance.
			\code
				// We have 3 IVar object, add the first 2 and store the result to the 3rd.
				Ref<IVar> a , b , c;

				// Get float value in a & b.
				float va = 0 , vb = 0;
				XS_VERIFY( a->GetFloat( va ) );
				XS_VERIFY( b->GetFloat( vb ) );

				// Set c = a + b
				c->SetFloat( va + vb );

			\endcode

			<BR>
			Before we access the value, we can get the type of value by \ref GetVarTypeID or \ref GetVarTypeName.<BR>
			These function should return basic type info while data is basic type and
			return IObject 's type info while data is an IObject instance.

		\sa	IOBJECTBASICTYPEGROUP, IObject::GetClassName, IObject::GetClassID

			<BR>
			IVar is also a low level value accessing protocol.
			In xeres, there's some higher level value wrapper such as IData or IAttribute.

		\sa	IData, IAttribute

		\remarks
			<I>Behaviors described above is followed inside native xeres implementation of IVar. If you implement your own
			IVar classes, you should follow this rules.</I>
	*/
	class IVar : public IObject
	{
	public:

		/// \name Constructor & Destructor
		//@{

		/// @ctor
		IVar( void );

		/// @dtor
		virtual ~IVar( void );

		//@}

		DECL_IOBJECT_INTERFACE( IVar , IObject );

	public:
		
		/// \name Variable Type RTTI
		//@{

		/*!
			\brief		Get variable type name.
			\details	Get type/class name of variable.<BR>
						Use return value to determine what type variable is.
			\sa			IOBJECTBASICTYPEGROUP
			\return		Type name.
		*/
		virtual const WString& GetVarTypeName( void ) const = 0;

		/*!
			\brief		Get internal data type id.
			\details	Get type/class ID of variable.<BR>
						Use return value to determine what type variable is.
			\sa			IOBJECTBASICTYPEGROUP
			\return		Type ID.
		*/
		virtual const ClassID GetVarTypeID( void ) const = 0;

		//@}

		/// \name Variable Manipulation
		//@{

		/*!
			\brief		Duplicate value from a given variable.
			\details	Duplicate value from a given variable, operation depend on source type.
						In most case implementation will release current data & set new data in.
						But in some implementation(such as IData) duplication is disabled.
			\return		Duplicated variable. Different implementation type or
						different internal data type could cause duplication failure.
			\param[in]	val		Source variable.
			
		*/
		virtual bool DuplicateFrom( const Ref<IVar>& val ) = 0;

		//@}

		/// \name Variable Accessors
		///	\details	These accessors are used for get & set value.<BR>
		///				If source/destination type mismatched, false will be return to indicate.
		//@{

		/// \brief	Set boolean value.
		virtual bool SetBool( bool val ) = 0;
		/// \brief	Set integer value.
		virtual bool SetInt( int val ) = 0;
		/// \brief	Set float value.
		virtual bool SetFloat( float val ) = 0;
		/// \brief	Set pair value.
		virtual bool SetPair( const Pair<float>& val ) = 0;
		/// \brief	Set vector value.
		virtual bool SetVector( const Vector<float>& val ) = 0;
		/// \brief	Set quaternion value.
		virtual bool SetQuat( const Quat<float>& val ) = 0;
		/// \brief	Set color value.
		virtual bool SetColor( const Color4& val ) = 0;
		/// \brief	Set matrix value.
		virtual bool SetMatrix( const Matrix<float>& val ) = 0;
		/// \brief	Set string value.
		virtual bool SetString( const WString& val ) = 0;

		/// \brief	Set IObject instance.
		virtual bool SetObject( RefWeak<IObject> val ) = 0;

		/// \brief	Get boolean value.
		virtual bool GetBool( bool& val ) const = 0;
		/// \brief	Get integer value.
		virtual bool GetInt( int& val ) const = 0;
		/// \brief	Get float value.
		virtual bool GetFloat( float& val ) const = 0;
		/// \brief	Get pair value.
		virtual bool GetPair( Pair<float>& val ) const = 0;
		/// \brief	Get vector value.
		virtual bool GetVector( Vector<float>& val ) const = 0;
		/// \brief	Get quaternion value.
		virtual bool GetQuat( Quat<float>& val ) const = 0;
		/// \brief	Get color value.
		virtual bool GetColor( Color4& val ) const = 0;
		/// \brief	Get matrix value.
		virtual bool GetMatrix( Matrix<float>& val ) const = 0;
		///	\brief	Get string value.
		virtual bool GetString( WString& val ) const = 0;

		/// \brief	Get IObject instance.
		virtual bool GetObject( Ref<IObject>& val ) const = 0;

		//@}

		/// \name Attribute Accessors
		///	\details	These accessors are used for script object attributes.<BR>
		//@{

		/// \brief Boolean attribute.
		bool AttrBool( void ) const { bool b; GetBool(b); return b; }

		/// \brief Integer attribute.
		int AttrInt( void ) const { int i; GetInt(i); return i; }

		/// \brief Float attribute.
		float AttrFloat( void ) const { float f; GetFloat(f); return f; }

		/// \brief Pair attribute.
		Pair<float> AttrPair( void ) const { Pair<float> p; GetPair(p); return p; }

		/// \brief Vector attribute.
		Vector<float> AttrVector( void ) const { Vector<float> v; GetVector(v); return v; }

		/// \brief Quat attribute.
		Quat<float> AttrQuat( void ) const { Quat<float> q; GetQuat(q); return q; }

		/// \brief Matrix attribute.
		Matrix<float> AttrMatrix( void ) const { Matrix<float> m; GetMatrix(m); return m ;}

		/// \brief String attribute.
		WString AttrString( void ) const { WString str; GetString(str); return str; }

		/// \brief Object attribute.
		template<
			typename _IObjectClass
		> Ref<_IObjectClass> AttrObject( void ) { Ref<IObject> obj; GetObject(obj); return Ref<_IObjectClass>(obj); }

		//@}
	};

} // namespace xeres
